#pragma once
#include "public.hpp"
using namespace std;

class UdpClient
{
private:
    string _ip;
    uint16_t _port;
    int _sockfd;

public:
    UdpClient() {}

    UdpClient(string ip, uint16_t port) : _ip(ip), _port(port)
    {
    }



    void Init()
    {
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0); // UDP
        if (_sockfd < 0)
        {
            Log(Fatal, "socket create error");
            exit(SOCK_CREATE_ERROR);
        }
        // socket创建成功, 客户端初始化完成

        // 客户端不需要进行绑定，在向服务端发送消息时OS自动完成
    }

    void GetInfo()
    {
        char buffer[1024]; bzero(buffer, 0);  
        struct sockaddr_in server; bzero(&server, 0);
        socklen_t len = sizeof(server);

        while (true)
        {               
            ssize_t realnum = recvfrom(_sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&server, &len);
            if (realnum > 0)
            {
                Analyze ret(server);
                buffer[realnum] = '\0';
                cout << "[client message from: " << ret.getip() << "]: " << buffer << endl;
            }    
        }
    }

    void SendInfo()
    {
        struct sockaddr_in goal;
        bzero(&goal, 0);
        goal.sin_family = AF_INET;
        goal.sin_addr.s_addr = inet_addr(_ip.c_str());
        goal.sin_port = htons(_port); // port主机序列转网络序列

        string str;
        while (true)
        {
            cout << "Please Enter# ";
            getline(cin, str);

            // 将消息发送给服务端
            ssize_t val = sendto(_sockfd, str.c_str(), str.size(), 0, (struct sockaddr *)&goal, sizeof(goal));
            if (val < 0)
            {
                Log(Error, "send clientinfo error");
		        perror("sendto:");
                continue;
            }
        }
    }

    void Start()
    {
        ThreadPool<function<void()>> *Pool = ThreadPool<function<void()>>::GetPool();

        Pool->ThreadInit();
        Pool->Start();

        function<void()> func1 = bind(&UdpClient::GetInfo, this);
        Pool->Push(func1);

        function<void()> func2 = bind(&UdpClient::SendInfo, this);
        Pool->Push(func2);

        Pool->Wait();
    }
};

    // void init_start()
    // {
    //     // 1. 创建套接字
    //     _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    //     if (_sockfd < 0)
    //     {
    //         cerr << "socket create fail" << endl;
    //         exit(2);
    //     }
    //     cout << "socket create sucess" << " socketfd = " << _sockfd << endl;

    //     // 2. 不需要用户自己绑定socket和网络信息，OS会自动绑定
    //     // 客户端构建目标主机信息

    //     struct sockaddr_in goal;
    //     bzero(&goal, 0);
    //     goal.sin_family = AF_INET;
    //     goal.sin_addr.s_addr = inet_addr(_ip.c_str());
    //     goal.sin_port = htons(_port); // port主机序列转网络序列

    //     string str;
    //     while (true)
    //     {
    //         cout << "Please Enter# ";
    //         getline(cin, str);

    //         //将消息发送给服务端
    //         sendto(_sockfd, str.c_str(), str.size(), 0, (struct sockaddr *)&goal, sizeof(goal));

    //         struct sockaddr_in peer;
    //         socklen_t len = sizeof(peer);
    //         char buffer[1024];
    //         //接收来自服务端的消息
    //         ssize_t n = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);
    //         if (n > 0)
    //         {
    //             buffer[n] = 0;
    //             std::cout << "server echo# " << buffer << std::endl;
    //         }
    //     }
    // }